// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: daniel

#include "coin2/exchange/bybit_futures/api_order_v3/native_rest_async_asio_subscriber.h"

#include <functional>

#include "coin2/exchange/bybit_futures/symbology/product.h"

namespace coin2::exchange::bybit_futures::api_order_v3 {

void BybitFuturesRestAsyncAsioSubscriber::QueryBalance() {
  auto http_context = rest_client()->QueryBalance();
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BybitFuturesRestAsyncAsioSubscriber::QueryPosition(const std::string& settle_coin) {
  RestParams params;
  params.set_coin(settle_coin);
  auto http_context = rest_client()->QueryPosition(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BybitFuturesRestAsyncAsioSubscriber::QueryOpenOrders(const std::string& settle_coin) {
  RestParams params;
  params.set_coin(settle_coin);
  auto http_context = rest_client()->QueryOpenOrders(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BybitFuturesRestAsyncAsioSubscriber::QueryDoneOrders(const std::string& native_symbol) {
  RestParams params;
  params.set_symbol(native_symbol);
  auto http_context = rest_client()->QueryDoneOrders(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BybitFuturesRestAsyncAsioSubscriber::QueryFills(const std::string& native_symbol) {
  RestParams params;
  params.set_symbol(native_symbol);
  auto http_context = rest_client()->QueryFills(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BybitFuturesRestAsyncAsioSubscriber::SubscribeAsync() {
  AddPeriodicTask(
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::QueryBalance, this),
      config_.query_account_balance_period_sec(),
      "query_balance");

  const auto& settle_coin_list = symcache_->GetCurrenciesNativeUpper();

  AddPeriodicTask(
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::QueryPosition, this, std::placeholders::_1),
      config_.query_account_position_period_sec(),
      "query_position",
      settle_coin_list);

  AddPeriodicTask(
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::QueryOpenOrders, this, std::placeholders::_1),
      config_.query_open_orders_period_sec(),
      "query_open_orders",
      settle_coin_list);

  const auto& symbol_list = native_symbols();

  AddPeriodicTask(
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::QueryDoneOrders, this, std::placeholders::_1),
      std::bind(
          &BybitFuturesRestAsyncAsioSubscriber::SkipQuery,
          this,
          "query_history_orders",
          std::placeholders::_1),
      config_.query_cancel_orders_period_sec(),
      "query_history_orders",
      symbol_list);

  AddPeriodicTask(
      std::bind(&BybitFuturesRestAsyncAsioSubscriber::QueryFills, this, std::placeholders::_1),
      std::bind(
          &BybitFuturesRestAsyncAsioSubscriber::SkipQuery,
          this,
          "query_fills",
          std::placeholders::_1),
      config_.query_fill_period_sec(),
      "query_fills",
      symbol_list);
}

}  // namespace coin2::exchange::bybit_futures::api_order_v3
